import os
import build_file.call_state
import dep_graph.keys
import logging

logger = logging.getLogger(__name__)


class BuildRuleCachedGraph(object):
  def __init__(self, config, graph):
    self.graph = graph
    self._config = config
    self.call_state = dict()
    for variant in config.variants():
      self.call_state[variant] = build_file.call_state.CallState(config, self, variant)
      for fname in config.files:
        self.load_config_file(variant, fname)
      for fname_tuple in config.builtin_files:
        self.load_builtin_config_file(variant, *fname_tuple)

  def get_rule_with_key(self, key):
    try:
      rule = self.graph.get_gen_rule_with_key(key)
      if rule:
        rule.out
        return rule
    
      rule = self.call_state[key.variant].get_gen_rule_with_key(key)
      return rule
    except:
      self.graph.try_delete_gen_rule_with_key(key)
      raise

  def load_builtin_config_file(self, variant, path, module):
    """Loads a builtin config or genrule definition file into the call_state.

    Args:
      variant: string, The variant to load the file into.
      fname: string, The tuple of library path, module to load.
    """
    self.call_state[variant].load_builtin_config_file(path, module)

  def load_config_file(self, variant, fname):
    """Loads a config or genrule definition file into the call_state.

    Args:
      variant: string, The variant to load the file into.
      fname: string, The filename to load.
    """
    self.call_state[variant].load_config_file(fname)

  def create_gen_rule(self, key):
    """Creates a new dep_graph.cache_view.GenRule for key.

    Args:
      key: The key for the new GenRule.

    Returns the newly created GenRule."""
    dirname = self.call_state[key.variant].getCallingFile()

    if dirname == ".":
      fname = "BUILD"
    else:
      fname = self.call_state[key.variant].getCallingFile() + "/BUILD"
    self.graph.add_gen_rule_to_build_file(fname, key)
    return self.graph.create_gen_rule_for_key(key)

  def addedBuildFiles(self):
    loaded_files = set()
    for variant, call_state in self.call_state.items():
      loaded_files |= call_state.loaded_files
    return loaded_files

  def getRecursiveRules(self, pathname, variant):
    logger.info('Getting recursive rules for: ' + pathname)
    for dirname, dirs, files in os.walk(pathname):
      if pathname == '.' and dirname != '.':
        # strip off './'
        dirname = dirname[2:]
      if "BUILD" in files:
        for name in self.call_state[variant].get_rules_in_directory(dirname):
          yield dep_graph.keys.GenRuleKey(dirname, name, variant)
